/*
 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * Contributors:
 *     bstefanescu
 */
package org.nuxeo.gwt.habyt.upload.client;

import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;

/**
 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
 * 
 */
public abstract class FilesView extends Composite implements FileEventHandler {

    protected Uploader uploader;

    protected HandlerRegistration hreg;

    public FilesView() {
        this(null);
    }

    public FilesView(Uploader uploader) {
        this.uploader = uploader;
        Widget widget = createWidget();
        widget.addStyleName("upload-files-view");
        initWidget(widget);
    }

    protected abstract Widget createWidget();

    protected abstract FileView getFileView(FileRef file);

    protected abstract void addFileView(FileView view);

    protected abstract FileView createFileView(FileRef file);

    public void addFile(FileRef file) {
        FileView view = createFileView(file);
        addFileView(view);
        if (file.getStatus() == FileRef.QUEUED) {
            view.onUploading();
        } else {
            file.setStatus(FileRef.STORED);
            view.onStored();
        }
    }

    public void removeFile(FileRef file) {
        FileView view = getFileView(file);
        if (view != null) {
            view.removeFromParent();
        } else {
            throw new IllegalStateException("File view not found for: " + file);
        }
    }

    public void updateFile(FileRef file) {
        FileView view = getFileView(file);
        if (view == null) {
            throw new IllegalStateException("File view not found for: " + file);
        }
        switch (file.getStatus()) {
        case FileRef.UPLOADING:
            view.onUploading();
            break;
        case FileRef.UPLOADED:
            view.onUploadDone();
            break;
        case FileRef.STORED:
            view.onStored();
            break;
        case FileRef.ERROR:
            view.onUploadError();
            break;
        }
    }

    @Override
    protected void onLoad() {
        registerFileEventHandler();
    }

    @Override
    protected void onUnload() {
        unregisterFileEventHandler();
    }

    protected void registerFileEventHandler() {
        if (hreg == null && uploader != null) {
            hreg = uploader.addFileEventHandler(this);
        }
    }

    protected void unregisterFileEventHandler() {
        if (hreg != null) {
            hreg.removeHandler();
            hreg = null;
        }
    }

    public void setUploader(Uploader uploader) {
        unregisterFileEventHandler();
        this.uploader = uploader;
        registerFileEventHandler();
    }

    public Uploader getUploader() {
        return uploader;
    }

    @Override
    public Widget getWidget() {
        return super.getWidget();
    }

    @Override
    public void onFileEvent(FileEvent event) {
        FileRef file = event.getFileRef();
        switch (file.getStatus()) {
        case FileRef.QUEUED:
            addFile(file);
            break;
        case FileRef.REMOVED:
            removeFile(file);
            break;
        default: // update the status
            updateFile(file);
            break;
        }
    }
}
